% Authors: Francisco Pinto & Bruno Maia
% Date: 22-09-2011
%
% This file is part of "Breakthrough"

% User Interface

?- ensure_loaded('breakthrough.pro').
?- ensure_loaded('persistence.pro').
?- ensure_loaded('constants.pro').

?- dynamic player_difficulty/2.


% query_difficulty/1
% Modes: (-)
% Asks the user for Player's difficulty
query_difficulty(Player) :- 
  nl, write('Pick a difficulty for this player:'), nl,
  write('1) Easy'), nl,
  write('2) Medium'), nl,
  write('3) Hard'), nl,
  write('-> '), get_code(DifficultySuggestion), get_char(_),
  Difficulty is DifficultySuggestion - 48, % '0' ASCII code
  (valid_difficulty(Difficulty) 
    -> assert(player_difficulty(Player, Difficulty))
    ;  write('Invalid input!'), nl, query_difficulty(Player)
   ).

% write_element/2
% Modes: (+,+)
% Writes a board element to stdout
write_element(Elem, SubIndex) :-
  player1_representation(Elem),
  player1_piece(P1, SubIndex),
  horizontal_separator_piece(S),
  write(P1), write(S).
  
write_element(Elem, SubIndex) :-
  player2_representation(Elem),
  player2_piece(P2, SubIndex),
  horizontal_separator_piece(S),
  write(P2), write(S).

write_element(Elem, SubIndex) :-
  blank_representation(Elem),
  blank_piece(B, SubIndex),
  horizontal_separator_piece(S),
  write(B), write(S).

% print_board/1
% Modes: (+)
% Prints the board to stdout
print_board(Board) :-
  board_size(Size),
  write('  '), print_horizontal_numbers(0), nl,
  write('  '), print_horizontal_separator(Size), nl,
  print_board(Board, 0).

print_board([], _).

print_board([Head|Tail], Index) :-
  board_size(Size),
  horizontal_separator_piece(Sep),
  format('~w ~w', [Index,Sep]), print_row(Head, 1), nl,
  format('  ~w', [Sep]), print_row(Head, 2), nl,
  write('  '), print_horizontal_separator(Size),
  nl,
  NewIndex is Index + 1,
  print_board(Tail, NewIndex).

print_row([], _).

print_row([Head|Tail], SubIndex) :-
  write_element(Head, SubIndex),
  print_row(Tail, SubIndex).

print_horizontal_numbers(Size) :-
  board_size(Size).

print_horizontal_numbers(Index) :-
  board_size(Size),
  Index < Size,
  format(' ~w   ', [Index]),
  NewIndex is Index + 1,
  print_horizontal_numbers(NewIndex).

print_horizontal_separator(0) :-
  write(+).

print_horizontal_separator(Size) :-
  Size > 0,
  vertical_separator_piece(Sep),
  write(Sep),
  NewSize is Size-1,
  print_horizontal_separator(NewSize).

type_to_upper('h', 'H').
type_to_upper('H', 'H').
type_to_upper('c', 'C').
type_to_upper('C', 'C').

player(Num, Type) :-
  format('Type of player number ~w?~n',[Num]),
  write(' H) Human'), nl,
  write(' C) CPU'), nl, nl,
  write('-> '),
  get_char(TypeSuggestion), get_char(_),
  (type_to_upper(TypeSuggestion, UpperCasedTypeSuggestion),
   check_valid_player_type(UpperCasedTypeSuggestion) 
  -> Type = UpperCasedTypeSuggestion
  ;  write('Invalid input, try again'), nl, player(Num, Type)
  ).

check_valid_player_type('H').
check_valid_player_type('C').

% print_winner/1
% Modes: (+)
% Writes a congratulatory message relating to Winner to stdout
print_winner(Winner) :-
  player_text(Winner, PlayerText),
  write('Congratulations, '), write(PlayerText), write('. You won!').  

% query_position/1
% Modes: (+, -, -)
% Asks the user for a cartesian position with Message as the header
query_position(Message, X, Y) :- 
  write(Message), nl,
  write('Position ("X-Y."): \n-> '),
  read(X-Y), get_char(_).

valid_movement_menu_option('1').
valid_movement_menu_option('2').

process_movement_menu_option(_, _, '1').

process_movement_menu_option(Board, Player, '2') :-
  save_game_and_exit([Board, Player]).


% movement_menu/2
% Modes: (+,+)
% Menu for each player's turn
movement_menu(Board, Player) :-
  player_text(Player, Text),
  format('~w\'s turn~n',[Text]),
  write('1) Play'), nl,
  write('2) Save and exit'), nl,
  get_char(Option), get_char(_),
  (valid_movement_menu_option(Option)
    -> process_movement_menu_option(Board, Player, Option)
    ; write('Invalid option!'), nl, movement_menu(Board, Player)). 


valid_main_menu_option('1').
valid_main_menu_option('2').

% movement_menu/2
% Modes: (+,+)
% The game's main menu
main_menu(Board, Player) :-
  write('1) New game'), nl,
  write('2) Load game'), nl,
  write('-> '), get_char(Option), get_char(_),
  (valid_main_menu_option(Option)
    -> process_option(Board, Player, Option)
    ;  write('Invalid choice'), main_menu(Board, Player)
  ).

process_option(Board, Player, '2') :-
  load_game([Board, Player])
    ; (
        write('Couldn\'t open save file!'), nl,
        process_option(Board, Player, '1')
      ).

process_option(Board, Player, '1') :-
  initial_board(Board),
  player1_representation(Player).